#include<time.h>
#include<string>
#include<stdio.h>
#include<stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

#define Screen 1
#define Onefile 2
#define ClassFile 3

#define SIZE 1024

#define Logfile "log.txt"

class Log{
public:
    Log()
    {
        printMethod=Screen;
        path="./log/";
    }

    void Enable(int method)
    {
        printMethod=method;
    }

    std::string levelToString(int level)
    {
        switch(level)
        {
            case Info:
                return "Info";
            case Debug:
                return "Debug";
            case Warning:
                return "Warning";
            case Error:
                return "Error";
            case Fatal:
                return "Fatal";
            default:
                return "None";
        }
    }

    void printfOneFile(const std::string& logtxt,const std::string& pathname)
    {
        std::string _pathname=path+pathname;
        int fd=open(_pathname.c_str(),O_WRONLY|O_CREAT|O_APPEND);
        write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }

    void printfClassFile(int level,const std::string& logtxt)
    {
        std::string st=Logfile;
        st+=".";
        st+=levelToString(level);
        std::cout<<st<<std::endl;
        printfOneFile(logtxt,st);
    }

    void printLog(int level,const std::string& logtxt)
    {
        switch(printMethod)
        {
            case Screen:
                std::cout<<logtxt<<std::endl;
                break;
            case Onefile:
                printfOneFile(logtxt,Logfile);
                break;
            case ClassFile:
                printfClassFile(level,logtxt);
                break;
            default:
                std::cout<<"None";
        }
    }

    void operator()(int level,const char* format,...)
    {
        time_t t=time(nullptr);
        struct tm *TM=localtime(&t);

        std::string ll=levelToString(level);
        char leftbuffer[SIZE];
        snprintf(leftbuffer,sizeof(leftbuffer),"[%s] [%d年%d月%d日 %d:%d:%d]",ll.c_str(),TM->tm_year+1900,TM->tm_mon+1,
        TM->tm_mday,TM->tm_hour,TM->tm_min,TM->tm_sec);

        //buffer[strlen(buffer)]
        //printf("%s",buffer);

        char rightbuffer[SIZE];
        va_list s;
        va_start(s,format);
        vsnprintf(rightbuffer,sizeof(rightbuffer),format,s);

        va_end(s);

        char logtxt[SIZE*2];
        snprintf(logtxt,sizeof(logtxt),"%s %s \n",leftbuffer,rightbuffer);
        printLog(level,logtxt);
    }

private:
    int printMethod;
    std::string path;
};